package com.wjk.kylin.modules.system.user.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wjk.kylin.core.common.redis.RedisRepository;
import com.wjk.kylin.core.constant.Constants;
import com.wjk.kylin.core.exception.BusinessException;
import com.wjk.kylin.core.exception.RequestException;
import com.wjk.kylin.core.security.TokenUtil;
import com.wjk.kylin.core.utils.HttpContextUtils;
import com.wjk.kylin.core.utils.IpUtils;
import com.wjk.kylin.core.utils.SecurityUtils;
import com.wjk.kylin.modules.system.config.service.IConfigService;
import com.wjk.kylin.modules.system.dept.service.IDeptService;
import com.wjk.kylin.modules.system.user.entity.User;
import com.wjk.kylin.modules.system.user.mapper.UserMapper;
import com.wjk.kylin.modules.system.user.service.IUserPositionService;
import com.wjk.kylin.modules.system.user.service.IUserRoleService;
import com.wjk.kylin.modules.system.user.service.IUserService;
import com.wjk.kylin.modules.system.user.vo.UserImportVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wangjkui
 * @since 2020-06-01
 */
@Slf4j
@Service
@Transactional(readOnly=true)
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    @Autowired
    private RedisRepository redisRepository;
    @Autowired
    private TokenUtil jwtTokenUtil;
    @Autowired
    private IUserPositionService userPositionService;
    @Autowired
    private IUserRoleService userRoleService;
    @Autowired
    private IDeptService deptService;
    @Autowired
    private IConfigService configService;
    @Override
    public IPage<User> findPage(Page<User> page, User user) {

        // 查询部门当前节点的所有子节点id
        List<String> deptIds = new ArrayList<>();

        if(user != null && StringUtils.isNotBlank(user.getDeptId())){
            deptIds.add(user.getDeptId());

            deptService.listWithId(deptService.list(),deptIds,user.getDeptId());
        }

        return baseMapper.findPage(page,user,deptIds);
    }

    @Override
    @DS("slave")//todo 数据源从库 会自动带上 del_flag = 0
    public User getUserByUserName(String userName) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", userName);
        wrapper.select("id","user_name","password","status");
        return this.getOne(wrapper);
    }

    @Override
    @Transactional(readOnly=false)
    public Map<String, Object> login(String username,String password,String code,String uuid){
        log.info("-----登录-----username:{},code:{},uuid:{}", username,code,uuid);

        String verifyKey = Constants.CAPTCHA_CODE_KEY + uuid;
        String captcha = redisRepository.get(verifyKey);

        redisRepository.del(verifyKey);

        if (StringUtils.isBlank(captcha)) {
            throw new RequestException("验证码失效，请重新获取");
        }else if (!StringUtils.equalsIgnoreCase(captcha,code)){
            throw new RequestException("验证码错误，请重新输入");
        }

        //获取token
        Map<String, Object> token = jwtTokenUtil.getToken(username, password);

        //1.更新登录时间 ip
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();
        wrapper.eq("user_name", username);
        wrapper.set("update_by",SecurityUtils.getUsername());
        wrapper.set("update_date",new Date());
        wrapper.set("login_date",new Date());
        wrapper.set("login_ip",IpUtils.getIpAddr(HttpContextUtils.getHttpServletRequest()));// 请求的地址
        super.update(wrapper);

        return token;
    }


    @Override
    @Transactional(readOnly=false)
    public boolean save(User user) throws BusinessException {
        //判断判断user_name唯一
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", user.getUserName());
        int count = this.count(wrapper);
        if(count > 0){
            throw new BusinessException("用户账号已存在，请求重新添加");
        }
        //前端传递初始化密码
        user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));

        user.preInsert();

        //1.保存用户数据
        boolean flag = super.save(user);

        if(flag){
            //1.保存用户岗位
            if(user.getPositionIds() != null && user.getPositionIds().length>0){
                userPositionService.save(user.getId(),Arrays.asList(user.getPositionIds()));
            }

            //2.保存用户角色
            if(user.getRoleIds() != null && user.getRoleIds().length>0){
                userRoleService.save(user.getId(),Arrays.asList(user.getRoleIds()));
            }
        }

        return flag;
    }

    @Override
    @Transactional(readOnly=false)
    public boolean update(User user) throws BusinessException{
        //判断判断user_name唯一
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", user.getUserName());
        wrapper.ne("id", user.getId());
        int count = this.count(wrapper);
        if(count > 0){
            throw new BusinessException("用户账号已存在，请求重新修改");
        }

        user.preUpdate();

        //1.保存用户数据
        boolean flag = super.updateById(user);

        if(flag){
            //删除数据
            userPositionService.deleteByUserIds(Arrays.asList(user.getId()));
            userRoleService.deleteByUserIds(Arrays.asList(user.getId()));
            //1.保存用户岗位
            if(user.getPositionIds() != null && user.getPositionIds().length>0){
                userPositionService.save(user.getId(),Arrays.asList(user.getPositionIds()));
            }
            //2.保存用户角色
            if(user.getRoleIds() != null && user.getRoleIds().length>0){
                userRoleService.save(user.getId(),Arrays.asList(user.getRoleIds()));
            }

        }

        return flag;
    }

    @Override
    @Transactional(readOnly=false)
    public boolean deleteByIds(String[] userIds) {
        List<String> list = Arrays.asList(userIds);
        //1.删除用户岗位
        userPositionService.deleteByUserIds(list);
        //2.删除用户角色
        userRoleService.deleteByUserIds(list);

        return super.removeByIds(list);
    }

    @Override
    @Transactional(readOnly=false)
    public boolean changeStatus(String userId, String status) {
        User user = super.getById(userId);

        if (StringUtils.isNotBlank(status) && !status.equals(user.getStatus())){
            user.setStatus(status);
            user.preUpdate();

            return super.updateById(user);
        }

        return false;
    }

    @Override
    @Transactional(readOnly=false)
    public boolean resetPwd(String userId, String password) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();

        wrapper.set("update_by",SecurityUtils.getUsername());
        wrapper.set("update_date",new Date());
        wrapper.set("password", SecurityUtils.encryptPassword(password));
        wrapper.eq("id", userId);

        return super.update(wrapper);
    }

    @Override
    @Transactional(readOnly=false)
    public boolean updateAvatar(String userId, String fileUrl) {
        UpdateWrapper<User> wrapper = new UpdateWrapper<>();

        wrapper.set("update_by",SecurityUtils.getUsername());
        wrapper.set("update_date",new Date());
        wrapper.set("avatar", fileUrl);
        wrapper.eq("id", userId);

        return super.update(wrapper);
    }

    @Override
    @Transactional(readOnly=false)
    public boolean saveImportData(List<UserImportVO> list) {
        //账号唯一性
        //长度验证
        //等等

//        List<User> userList = new ArrayList<>();

//        list.forEach(l->{
//            User u = new User();
//            BeanUtils.copyProperties(l,u);
//
//            userList.add(u);
//        });


        List<User> userList = list.stream().map(l -> {
            User u = new User();
            BeanUtils.copyProperties(l, u);

            u.preInsert();//初始化公共参数

            u.setPassword(SecurityUtils.encryptPassword(configService.getConfigKey("sys.user.initPassword")));//设置密码

            return u;
        }).collect(Collectors.toList());

        return super.saveBatch(userList);
    }

}
